package org.dromara.wms.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.web.core.BaseService;
import org.dromara.fms.domain.FmsBill;
import org.dromara.fms.service.impl.FmsBillServiceImpl;
import org.dromara.wms.domain.WmsOrder;
import org.dromara.wms.domain.WmsOrderLine;
import org.dromara.wms.domain.WmsOrderType;
import org.dromara.wms.mapper.WmsOrderLineMapper;
import org.dromara.wms.mapper.WmsOrderMapper;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 测试主从Service业务层处理
 *
 * @author wenrui Su
 * @date 2024-03-24
 */
@RequiredArgsConstructor
@Service
public class WmsOrderServiceImpl extends BaseService {

  private final WmsOrderMapper baseMapper;

  private final WmsOrderLineMapper lineMapper;

  private final WmsStockService stockService;

  private final FmsBillServiceImpl fmsBillService;

  private final WmsOrderTypeServiceImpl wmsOrderTypeService;

  /**
   * 查询订单列表ById
   */
  public WmsOrder queryById(Long id) {
    return baseMapper.selectById(id);
  }

  /**
   * 查询订单主从列表
   */
  public TableDataInfo<WmsOrder> queryPageList(WmsOrder bo, PageQuery pageQuery) {
    Page<WmsOrder> result = baseMapper.queryPageList(pageQuery.build(), bo);
    return TableDataInfo.build(result);
  }

  /**
   * 查询订单列表
   */
  public List<WmsOrder> queryList(WmsOrder bo) {
    LambdaQueryWrapper<WmsOrder> lqw = buildQueryWrapper(bo);
    return baseMapper.selectList(lqw);
  }

  private LambdaQueryWrapper<WmsOrder> buildQueryWrapper(WmsOrder bo) {
    Map<String, Object> params = bo.getParams();
    LambdaQueryWrapper<WmsOrder> lqw = Wrappers.lambdaQuery();
    lqw.like(StringUtils.isNotBlank(bo.getName()), WmsOrder::getName, bo.getName());
    lqw.eq(bo.getId() != null, WmsOrder::getId, bo.getId());
    lqw.eq(bo.getPartnerId() != null, WmsOrder::getPartnerId, bo.getPartnerId());
    lqw.eq(bo.getStatus() != null, WmsOrder::getStatus, bo.getStatus());
    lqw.eq(bo.getTypeId() != null, WmsOrder::getTypeId, bo.getTypeId());
    lqw.eq(bo.getSourceId() != null, WmsOrder::getSourceId, bo.getSourceId());
    lqw.between(params.get("beginUpdateTime") != null && params.get("endUpdateTime") != null,
      WmsOrder::getUpdateTime, params.get("beginUpdateTime"), params.get("endUpdateTime"));
    return lqw;
  }

  /**
   * 新增订单主从
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> insertByBo(WmsOrder bo) throws WmsStockService.emptyException {
//  新增主表
    validEntityBeforeSave(bo);
    boolean flag = baseMapper.insert(bo) > 0;
//  新增子表
    List<WmsOrderLine> lineList = bo.getLine();
    for (WmsOrderLine line : lineList) {
      line.setId(bo.getId());
      line.setWhId(bo.getSelfWhId());
      if (line.getBatchCode() == null || line.getBatchCode().isEmpty()){
        line.setBatchCode("0");
      }
      this.insertLineByBo(line);
      }

    HashSet<Long> typeIds = new HashSet<>();

    typeIds.add(15L);//零售退货单据类别
    typeIds.add(14L);//零售订单类别
    if (typeIds.contains(bo.getTypeId())){
      //直接执行订单
      R<Void> res =  this.execByBo(bo);
      if (R.isError(res)){
        return res;
      }
      //统计应收金额和实收金额
      WmsOrderLine wmsOrderLine = countBillMoney(bo.getId());
      FmsBill fmsBill = getFmsBill(bo, wmsOrderLine);
      //新增账单
      fmsBillService.insertByBo(fmsBill);
      //执行账单
      fmsBillService.execBill(fmsBill);
    }

    return (flag) ? R.ok("新增成功") : R.fail("新增失败");
  }

  @NotNull
  public FmsBill getFmsBill(WmsOrder bo, WmsOrderLine wmsOrderLine) {
    FmsBill fmsBill = new FmsBill();
    WmsOrderType wmsOrderType = wmsOrderTypeService.queryById(bo.getTypeId());

    fmsBill.setTypeId(wmsOrderType.getFmsTypeId());
    fmsBill.setName(bo.getName());
    fmsBill.setPartnerId(bo.getPartnerId());
    fmsBill.setSourceId(bo.getId());
    fmsBill.setOperId(bo.getApplicantId());
    fmsBill.setCostMoney(wmsOrderLine.getCostMoney());
    fmsBill.setMoney(wmsOrderLine.getTotalMoney());
    fmsBill.setAccountId(bo.getFmsAccount());
    fmsBill.setPlanTime(bo.getCreateTime());
    fmsBill.setExecutionTime(bo.getCreateTime());
    fmsBill.setStatus("1");
    fmsBill.setRemark(bo.getRemark());
    fmsBill.setTenantId(bo.getTenantId());
    fmsBill.setCreateDept(bo.getCreateDept());
    fmsBill.setCreateTime(bo.getCreateTime());
    fmsBill.setCreateBy(bo.getCreateBy());
    return fmsBill;
  }

  /**
   * 修改订单主从
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public Boolean updateByBo(WmsOrder bo) {

    validEntityBeforeSave(bo);

    if (bo.getLine() != null) {
      List<WmsOrderLine> lineList = bo.getLine();
      for (WmsOrderLine line : lineList) {
        if (line.getLineId() == null) {
          line.setId(bo.getId());
          line.setWhId(bo.getSelfWhId());
          this.insertLineByBo(line); // 子表新增
        } else {
          this.updateLineByBo(line); // 子表修改
        }
      }
    }

    return baseMapper.updateById(bo) > 0;
  }

  /**
   * 保存前的数据校验
   */
  private void validEntityBeforeSave(WmsOrder entity) {
    //TODO 做一些数据校验,如唯一约束
  }

  /**
   * 批量删除订单主从
   */
  @Transactional(propagation = Propagation.NESTED)
  public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
    if (isValid) {
      //TODO 做一些业务上的校验,判断是否需要校验
    }
    this.deleteLineWithValidByIds(ids, true);
    return baseMapper.deleteBatchIds(ids) > 0;
  }

  /**
   * 查询订单从========================================操作line表开始===============================
   */
  public List<WmsOrderLine> queryLineById(Long lineId) {
    return lineMapper.selectList(this.buildLineQueryWrapper(lineId));
  }

//统计应收金额和实收金额
  public WmsOrderLine countBillMoney(Long id) {
      return lineMapper.selectCountMoney(id);
  }

  /**
   * 查询订单从列表
   */
  public TableDataInfo<WmsOrderLine> queryLinePageList(WmsOrderLine bo, PageQuery pageQuery) {
    Page<WmsOrderLine> result = lineMapper.queryLinePageList(pageQuery.build(), bo);
    return TableDataInfo.build(result);
  }

  private LambdaQueryWrapper<WmsOrderLine> buildLineQueryWrapper(Long id) {
    LambdaQueryWrapper<WmsOrderLine> lqw = Wrappers.lambdaQuery();
    lqw.eq(id != null, WmsOrderLine::getId, id);
    return lqw;
  }

  /**
   * 新增订单从
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public Boolean insertLineByBo(WmsOrderLine bo) {
    validLineEntityBeforeSave(bo);
      return lineMapper.insert(bo) > 0;
  }

  /**
   * 修改订单从
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public Boolean updateLineByBo(WmsOrderLine bo) {
    validLineEntityBeforeSave(bo);
    return lineMapper.updateById(bo) > 0;
  }

  /**
   * 保存前的数据校验
   */
  private void validLineEntityBeforeSave(WmsOrderLine entity) {
    //TODO 做一些数据校验,如唯一约束
  }

  /**
   * 批量删除通过子表lineId
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public Boolean deleteWithValidByLineIds(Collection<Long> lineIds, Boolean isValid) {
    if (isValid) {
      //TODO 做一些业务上的校验,判断是否需要校验
    }
    return lineMapper.deleteBatchIds(lineIds) > 0;
  }

  /**
   * 通过主表ids删除子表
   *
   * @param ids
   * @param isValid
   * @return
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public Boolean deleteLineWithValidByIds(Collection<Long> ids, Boolean isValid) {
    if (isValid) {
      //TODO 做一些业务上的校验,判断是否需要校验
    }
    LambdaQueryWrapper<WmsOrderLine> lqw = new LambdaQueryWrapper<>();
    lqw.in(WmsOrderLine::getId, ids);
    return lineMapper.delete(lqw) > 0;
  }

  /**
   * 订单执行
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> execByBo(WmsOrder bo) throws WmsStockService.emptyException {
    //零售类订单可以没有合伙人
    if (bo.getTypeId() != 14 && bo.getTypeId() != 15 && bo.getPartnerId() == null){
      throw new WmsStockService.emptyException("未选择合伙人partnerId！");
    }
    if (!bo.getWmsType().equals("nothing")) {
      WmsOrderLine lineBo = new WmsOrderLine();
      lineBo.setId(bo.getId());
      List<WmsOrderLine> data = lineMapper.queryLinePageList(lineBo);
      if (!data.isEmpty()) {
        bo.setLine(data);
      }else{
        return R.fail("空订单，请检查后重试!");
      }
      stockService.execOrder(bo);
    }
    bo.setStatus("0");
      validEntityBeforeSave(bo);
      return toAjax(baseMapper.updateById(bo));
  }

  /**
   * 转采购订单
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> turnOrder(List<WmsOrder> orderList){
    R<Void> res;
    for (WmsOrder order : orderList) {
      if (Objects.equals(order.getStatus(), "0")){
        throw new WmsStockService.emptyException("所选单据包含已转换采购订单，请重新选择！");
      }
      if (!Objects.equals(orderList.get(0).getSelfWhId(), order.getSelfWhId())) {
        throw new WmsStockService.emptyException("所选单据仓库号不一致，请重新选择！");
      }
      if (order.getPartnerId() == null){
        throw new WmsStockService.emptyException("单据"+ order.getId() +" 未选择供应商！");
      }
      if (!order.getPartnerId().equals(orderList.get(0).getPartnerId())){
        throw new WmsStockService.emptyException("所选单据供应商不一致！");
      }
    }
    WmsOrder wmsOrder = new WmsOrder();
    for (WmsOrder bo : orderList) {
      WmsOrderLine lineBo = new WmsOrderLine();
      lineBo.setId(bo.getId());
      List<WmsOrderLine> data = lineMapper.queryLinePageList(lineBo);
      if (data.isEmpty()){
        throw new WmsStockService.emptyException("找不到 "+lineBo.getId()+" 下的明细表，请检查后重试！");
      }
      data.forEach(datum -> {
        datum.setLineId(null);
        datum.setId(null);
      });
      if (wmsOrder.getLine() == null || wmsOrder.getLine().isEmpty()){
        wmsOrder.setLine(data);
      }else{
        wmsOrder.getLine().addAll(data);
      }
      if (orderList.size() == 1){
        wmsOrder.setSourceId(bo.getSourceId());
      }
      if (wmsOrder.getRemark() == null || wmsOrder.getRemark().isEmpty()) {
        wmsOrder.setRemark(" 工单表 " + bo.getSourceId() + " 生产需求订单");
      }else{
        wmsOrder.setRemark(wmsOrder.getRemark() + " 工单表 " + bo.getSourceId() + " 生产需求订单");
      }
      bo.setStatus("0");
      baseMapper.updateById(bo);
    }
    wmsOrder.setPartnerId(orderList.get(0).getPartnerId());
    wmsOrder.setSelfWhId(orderList.get(0).getSelfWhId());
    wmsOrder.setName("工单表生产需求单");
    wmsOrder.setTypeId(22L);
    wmsOrder.setStatus("1");
    res = this.insertByBo(wmsOrder);
    return res;
  }

  /**
   * 订单冲销
   * */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> backByBo(WmsOrder wmsOrder) {
    R<Void> res = null;
    //更改订单状态为冲销
    wmsOrder.setStatus("8");
    baseMapper.updateById(wmsOrder);

    //判断有无冲销单
    WmsOrderType wmsOrderType = wmsOrderTypeService.queryById(wmsOrder.getTypeId());
    if (wmsOrder.getSourceId() == null){
      wmsOrder.setSourceId(wmsOrder.getId());
    }
    List<WmsOrder> wmsOrders =  baseMapper.selectList(this.buildWmsOrderQueryWrapper(wmsOrder.getSourceId(), (long) wmsOrderType.getBackId()));
    if (!wmsOrders.isEmpty()){
      throw new WmsStockService.emptyException("订单 "+wmsOrder.getName()+" 已有冲销单，请前往退货页面操作");
    }
    //获取订单列表
    List<WmsOrderLine> wmsOrderLineList = this.queryLineById(wmsOrder.getId());
    wmsOrderLineList.forEach(item->{item.setLineId(null);});
    wmsOrder.setId(null);
    wmsOrder.setStatus("1");
    wmsOrder.setLine(wmsOrderLineList);
    if(wmsOrder.getBackId() != null){
      wmsOrder.setTypeId(wmsOrder.getBackId());
    }else{
      wmsOrder.setTypeId((long) wmsOrderType.getBackId());
    }
    res = this.insertByBo(wmsOrder);
    return res;
  }

  private LambdaQueryWrapper<WmsOrder> buildWmsOrderQueryWrapper(Long id, Long typeId) {
    LambdaQueryWrapper<WmsOrder> lqw = Wrappers.lambdaQuery();
    lqw.eq(id != null, WmsOrder::getSourceId, id);
    lqw.eq(typeId != null, WmsOrder::getTypeId, typeId);
    return lqw;
  }

  /**
   * 财务结算
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> financialSettlement(WmsOrder order) {
    R<Void> res =  null;
    //判断有无冲销单
    if (order.getSourceId() == null){
      order.setSourceId(order.getId());
    }
    WmsOrderType wmsOrderType = wmsOrderTypeService.queryById(order.getTypeId());
    Long backId = order.getTypeId();
    if (wmsOrderType.getBackId() != null){
      backId = (long) wmsOrderType.getBackId();
    }
    List<WmsOrder> wmsOrders =  baseMapper.selectList(this.buildWmsOrderQueryWrapper(order.getSourceId(), backId));
    if (!wmsOrders.isEmpty()){
      throw new WmsStockService.emptyException("订单 "+order.getName()+" 已冲销，无法结算！");
    }
    //判断有无财务账单
    List<FmsBill> fmsBills = fmsBillService.queryListBySourceId(order.getId());
    if (!fmsBills.isEmpty()){
      throw new WmsStockService.emptyException("订单 "+order.getName()+" 已有财务结算单！");
    }
    //统计应收金额和实收金额
    WmsOrderLine wmsOrderLine = countBillMoney(order.getId());
    FmsBill fmsBill = getFmsBill(order, wmsOrderLine);

    //新增账单
    res = toAjax(fmsBillService.insertByBo(fmsBill));

    return res;
  }

  /**
   * pc商城查询订单主从列表
   */
  public TableDataInfo<WmsOrder> pcQueryPageList(WmsOrder bo, PageQuery pageQuery) {
    Page<WmsOrder> result = baseMapper.queryPageList(pageQuery.build(), bo);
    return TableDataInfo.build(result);
  }

  /**
   * pc商城新增订单主从
   */
  @Transactional(propagation = Propagation.REQUIRED)
  public R<Void> pcInsertByBo(WmsOrder bo) throws WmsStockService.emptyException {
    if (bo.getName().equals(null)){
      throw new WmsStockService.emptyException("订单名称空");
    }
    List<WmsOrder> wmsOrders = this.queryList(bo);
    if (wmsOrders.size() > 1){
      throw new WmsStockService.emptyException("查询出多个同名订单");
    }
    WmsOrder wmsOrder = new WmsOrder();
    if (wmsOrders.size() == 0){
      wmsOrder.setName(bo.getName());
      wmsOrder.setTypeId(8L);
      wmsOrder.setStatus("1");
      baseMapper.insert(wmsOrder);
    }
    List<WmsOrderLine> lineList = bo.getLine();
    for (WmsOrderLine line : lineList) {
      line.setId(wmsOrder.getId());
      if(wmsOrder.getSelfWhId() != null)
        line.setWhId(wmsOrder.getSelfWhId());
      if (line.getBatchCode() == null || line.getBatchCode().isEmpty()){
        line.setBatchCode("0");
      }
      this.insertLineByBo(line);
    }
    return R.ok("添加成功");
  }
}
